package com.billard.service.impl;


import com.billard.dto.ReservationDTO;
import com.billard.entity.Reservation;
import com.billard.entity.Table;
import com.billard.exception.AccountNotFoundException;
import com.billard.mapper.ReservationMapper;
import com.billard.mapper.TableMapper;
import com.billard.service.ReservationService;
import com.billard.websocket.TableStatusPublisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

// 在文件顶部导入新的工具类
import com.billard.utils.TimeUtils;

/**
 * 预约服务实现类
 */
@Service
public class ReservationServiceImpl implements ReservationService {

    @Autowired
    private ReservationMapper reservationMapper;

    @Autowired
    private TimeUtils timeUtils;

    @Autowired
    private TableMapper tableMapper;

    @Autowired
    private TableStatusPublisher tableStatusPublisher;

    @Override
    @Transactional
    // 修改createReservation方法中的时间计算逻辑
    public void createReservation(ReservationDTO reservationDTO) {
        // 验证球台状态
        Table table = tableMapper.selectById(reservationDTO.getTableId());
        if (table == null) {
            throw new AccountNotFoundException("球台不存在");
        }

        // 检查球台是否可预约
        if (table.getStatus() != 0) {
            throw new AccountNotFoundException("球台当前不可预约");
        }

        // 检查时间段是否冲突
        boolean hasConflict = hasTimeConflict(reservationDTO);
        if (hasConflict) {
            throw new AccountNotFoundException("该时间段已被预约");
        }

        Reservation reservation = new Reservation();
        reservation.setTableId(reservationDTO.getTableId());
        reservation.setCustomerName(reservationDTO.getCustomerName());
        reservation.setCustomerPhone(reservationDTO.getCustomerPhone());
        reservation.setStartTime(reservationDTO.getStartTime());
        reservation.setEndTime(reservationDTO.getEndTime());

        // 计算时长和费用
        try {
            long hours = timeUtils.calculateHoursBetween(reservationDTO.getStartTime(), reservationDTO.getEndTime());
            reservation.setDuration((int) hours);
            reservation.setFee(table.getHourlyPrice().multiply(BigDecimal.valueOf(hours)));
            reservation.setStatus(0); // 待确认

            reservationMapper.insert(reservation);

            // 发送预约提醒
            tableStatusPublisher.publishReservationReminder(
                "新预约：" + reservationDTO.getCustomerName() + " 预约 " + table.getTableName() +
                " 时间：" + reservationDTO.getStartTime().toLocalTime() + "-" + reservationDTO.getEndTime().toLocalTime()
            );
        } catch (IllegalArgumentException e) {
            // 记录异常信息并抛出自定义异常
            System.err.println("计算预约费用失败: " + e.getMessage());
            throw new RuntimeException("预约时间信息不完整，无法创建预约");
        }
    }


    @Override
    @Transactional
    public void confirmReservation(Long reservationId) {
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new AccountNotFoundException("预约不存在");
        }

        if (reservation.getStatus() != 0) {
            throw new AccountNotFoundException("预约状态不正确");
        }

        // 更新预约状态
        reservation.setStatus(1); // 已确认
        reservationMapper.update(reservation);

        // 更新球台状态为预约
        Table table = tableMapper.selectById(reservation.getTableId());
        if (table != null) {
            table.setStatus(2); // 预约
            table.setStartTime(reservation.getStartTime());
            table.setEndTime(reservation.getEndTime());
            tableMapper.update(table);

            // 发布状态变更
            tableStatusPublisher.publishTableStatusChange(table.getId());
        }
    }

    @Override
    public void cancelReservation(Long reservationId) {
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new AccountNotFoundException("预约不存在");
        }

        // 检查是否是客户在取消自己的预约
        // 这里可以添加更复杂的逻辑来验证用户身份
        // 例如，可以通过JWT中的用户信息来验证

        // 更新预约状态
        reservation.setStatus(2); // 已取消
        reservationMapper.update(reservation);

        // 如果球台状态是预约，则恢复为空闲
        Table table = tableMapper.selectById(reservation.getTableId());
        if (table != null && table.getStatus() == 2) {
            table.setStatus(0); // 空闲
            table.setStartTime(null);
            table.setEndTime(null);
            tableMapper.update(table);

            // 发布状态变更
            tableStatusPublisher.publishTableStatusChange(table.getId());
        }
    }

    @Override
    public List<Reservation> getAllReservations() {
        return reservationMapper.selectAll();
    }

    @Override
    public List<Reservation> getReservationsByStatus(Integer status) {
        return reservationMapper.selectByStatus(status);
    }

    @Override
    public List<Reservation> getReservationsByTableId(Long tableId) {
        return reservationMapper.selectByTableId(tableId);
    }

    @Override
    public void deleteReservation(Long id) {
        reservationMapper.deleteById(id);
    }

    @Override
    public Map<String, Object> getReservationStatistics(String startDate, String endDate) {
        return reservationMapper.selectStatistics(startDate, endDate);
    }

    /**
     * 检查时间冲突
     */
    private boolean hasTimeConflict(ReservationDTO reservationDTO) {
        // 调用Mapper方法检查时间冲突
        int conflictCount = reservationMapper.checkTimeConflict(
            reservationDTO.getTableId(),
            reservationDTO.getStartTime(),
            reservationDTO.getEndTime(),
            null // 新建预约，没有需要排除的ID
        );
        return conflictCount > 0;
    }
}
